home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Blender 2.49b / blender-2.49b-windows.exe / $_4_ / .blender / scripts / mesh_wire.py < prev    next >
Text File  |  2009-08-31  |  8KB  |  291 lines

  1. #!BPY
  2. """
  3. Name: 'Solid Wireframe'
  4. Blender: 243
  5. Group: 'Mesh'
  6. Tooltip: 'Make a solid wireframe copy of this mesh'
  7. """
  8.  
  9. # -------------------------------------------------------------------------- 
  10. # Solid Wireframe1.0 by Campbell Barton (AKA Ideasman42) 
  11. # -------------------------------------------------------------------------- 
  12. # ***** BEGIN GPL LICENSE BLOCK ***** 
  13. # This program is free software; you can redistribute it and/or 
  14. # modify it under the terms of the GNU General Public License 
  15. # as published by the Free Software Foundation; either version 2 
  16. # of the License, or (at your option) any later version. 
  17. # This program is distributed in the hope that it will be useful, 
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  20. # GNU General Public License for more details. 
  21. # You should have received a copy of the GNU General Public License 
  22. # along with this program; if not, write to the Free Software Foundation, 
  23. # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
  24. # ***** END GPL LICENCE BLOCK ***** 
  25. # --------------------------------------------------------------------------
  26. import Blender
  27. from Blender import Scene, Mesh, Window, sys
  28. from Blender.Mathutils import AngleBetweenVecs, TriangleNormal
  29. from BPyMesh import faceAngles # get angles for face cornders
  30. #import BPyMesh
  31. #reload(BPyMesh)
  32. #faceAngles = BPyMesh.faceAngles
  33.  
  34. # works out the distanbce to inset the corners based on angles
  35. from BPyMathutils import angleToLength
  36. #import BPyMathutils 
  37. #reload(BPyMathutils)
  38. #angleToLength = BPyMathutils.angleToLength
  39.  
  40. import mesh_solidify
  41.  
  42. import BPyMessages
  43. reload(BPyMessages)
  44. import bpy
  45.  
  46.  
  47. def solid_wire(ob_orig, me_orig, sce, PREF_THICKNESS, PREF_SOLID, PREF_SHARP, PREF_XSHARP):
  48.     if not PREF_SHARP and PREF_XSHARP:
  49.         PREF_XSHARP = False
  50.     
  51.     # This function runs out of editmode with a mesh
  52.     # error cases are alredy checked for
  53.     
  54.     inset_half = PREF_THICKNESS / 2
  55.     del PREF_THICKNESS
  56.     
  57.     ob = ob_orig.copy()
  58.     me = me_orig.copy()
  59.     ob.link(me)
  60.     sce.objects.selected = []
  61.     sce.objects.link(ob)
  62.     ob.sel = True
  63.     sce.objects.active = ob
  64.     
  65.     # Modify the object, should be a set
  66.     FGON= Mesh.EdgeFlags.FGON
  67.     edges_fgon = dict([(ed.key,None) for ed in me.edges if ed.flag & FGON])
  68.     # edges_fgon.fromkeys([ed.key for ed in me.edges if ed.flag & FGON])
  69.     
  70.     del FGON
  71.  
  72.     
  73.     
  74.     # each face needs its own verts
  75.     # orig_vert_count =len(me.verts)
  76.     new_vert_count = len(me.faces) * 4
  77.     for f in me.faces:
  78.         if len(f) == 3:
  79.             new_vert_count -= 1
  80.     
  81.     if PREF_SHARP == 0:
  82.         new_faces_edge= {}
  83.         
  84.         def add_edge(i1,i2, ni1, ni2):
  85.             
  86.             if i1>i2:
  87.                 i1,i2 = i2,i1
  88.                 flip = True
  89.             else:
  90.                 flip = False
  91.             new_faces_edge.setdefault((i1,i2), []).append((ni1, ni2, flip))
  92.         
  93.     
  94.     new_verts = []
  95.     new_faces = []
  96.     vert_index = len(me.verts)
  97.     
  98.     for f in me.faces:
  99.         f_v_co = [v.co for v in f]
  100.         angles = faceAngles(f_v_co)
  101.         f_v_idx = [v.index for v in f]
  102.         
  103.         def new_vert(fi):
  104.             co = f_v_co[fi]
  105.             a = angles[fi]
  106.             if a > 180:
  107.                 vert_inset = 1 * inset_half
  108.             else:
  109.                 vert_inset = inset_half * angleToLength( abs((180-a) / 2) )
  110.             
  111.             # Calculate the inset direction
  112.             co1 = f_v_co[fi-1]
  113.             co2 = fi+1 # Wrap this index back to the start
  114.             if co2 == len(f_v_co): co2 = 0
  115.             co2 = f_v_co[co2]
  116.             
  117.             co1 = co1 - co
  118.             co2 = co2 - co
  119.             co1.normalize()
  120.             co2.normalize()
  121.             d = co1+co2
  122.             # Done with inset direction
  123.             
  124.             d.length = vert_inset
  125.             return co+d
  126.         
  127.         new_verts.extend([new_vert(i) for i in xrange(len(f_v_co))])
  128.         
  129.         if len(f_v_idx) == 4:
  130.             faces = [\
  131.             (f_v_idx[1], f_v_idx[0], vert_index, vert_index+1),\
  132.             (f_v_idx[2], f_v_idx[1], vert_index+1, vert_index+2),\
  133.             (f_v_idx[3], f_v_idx[2], vert_index+2, vert_index+3),\
  134.             (f_v_idx[0], f_v_idx[3], vert_index+3, vert_index),\
  135.             ]
  136.         else:
  137.             faces = [\
  138.             (f_v_idx[1], f_v_idx[0], vert_index, vert_index+1),\
  139.             (f_v_idx[2], f_v_idx[1], vert_index+1, vert_index+2),\
  140.             (f_v_idx[0], f_v_idx[2], vert_index+2, vert_index),\
  141.             ]
  142.         
  143.         
  144.         if PREF_SHARP == 1:
  145.             if not edges_fgon:
  146.                 new_faces.extend(faces)
  147.             else:
  148.                 for nf in faces:
  149.                     i1,i2 = nf[0], nf[1]
  150.                     if i1>i2: i1,i2 = i2,i1
  151.                     
  152.                     if edges_fgon and (i1,i2) not in edges_fgon:
  153.                         new_faces.append(nf)
  154.             
  155.             
  156.         
  157.         elif PREF_SHARP == 0:
  158.             for nf in faces:
  159.                 add_edge(*nf)
  160.             
  161.         vert_index += len(f_v_co)
  162.     
  163.     me.verts.extend(new_verts)
  164.     
  165.     if PREF_SHARP == 0:
  166.         def add_tri_flipped(i1,i2,i3):
  167.             try:
  168.                 if AngleBetweenVecs(me.verts[i1].no, TriangleNormal(me.verts[i1].co, me.verts[i2].co, me.verts[i3].co)) < 90:
  169.                     return i3,i2,i1
  170.                 else:
  171.                     return i1,i2,i3
  172.             except:
  173.                 return i1,i2,i3
  174.         
  175.         # This stores new verts that use this vert
  176.         # used for re-averaging this verts location
  177.         # based on surrounding verts. looks better but not needed.
  178.         vert_users = [set() for i in xrange(vert_index)]
  179.         
  180.         for (i1,i2), nf in new_faces_edge.iteritems():
  181.             
  182.             if len(nf) == 2:
  183.                 # Add the main face
  184.                 if edges_fgon and (i1,i2) not in edges_fgon:
  185.                     new_faces.append((nf[0][0], nf[0][1], nf[1][0], nf[1][1]))
  186.                 
  187.                 
  188.                 if nf[0][2]:    key1 = nf[0][1],nf[0][0]
  189.                 else:            key1 = nf[0][0],nf[0][1]
  190.                 if nf[1][2]:    key2 = nf[1][1],nf[1][0]
  191.                 else:            key2 = nf[1][0],nf[1][1]
  192.                 
  193.                 # CRAP, cont work out which way to flip so make it oppisite the verts normal.
  194.                 
  195.                 ###new_faces.append((i2, key1[0], key2[0])) # NO FLIPPING, WORKS THOUGH
  196.                 ###new_faces.append((i1, key1[1], key2[1]))
  197.                 new_faces.append(add_tri_flipped(i2, key1[0], key2[0]))
  198.                 new_faces.append(add_tri_flipped(i1, key1[1], key2[1]))
  199.                 
  200.                 # Average vert loction so its not tooo pointy
  201.                 # not realy needed but looks better
  202.                 vert_users[i2].update((key1[0], key2[0]))
  203.                 vert_users[i1].update((key1[1], key2[1]))
  204.             
  205.             if len(nf) == 1:
  206.                 if nf[0][2]:    new_faces.append((nf[0][0], nf[0][1], i2, i1)) # flipped
  207.                 else:            new_faces.append((i1,i2, nf[0][0], nf[0][1]))
  208.                 
  209.         
  210.         # average points now.
  211.         for i, vusers in enumerate(vert_users):
  212.             if vusers:
  213.                 co = me.verts[i].co
  214.                 co.zero()
  215.                 
  216.                 for ii in vusers:
  217.                     co += me.verts[ii].co
  218.                 co /= len(vusers)
  219.     
  220.     me.faces.delete(1, range(len(me.faces)))
  221.     
  222.     me.faces.extend(new_faces)
  223.  
  224.     # External function, solidify
  225.     me.sel = True
  226.     if PREF_SOLID:
  227.         mesh_solidify.solidify(me, -inset_half*2, True, False, PREF_XSHARP)
  228.  
  229.  
  230. def main():
  231.     
  232.     # Gets the current scene, there can be many scenes in 1 blend file.
  233.     sce = bpy.data.scenes.active
  234.     
  235.     # Get the active object, there can only ever be 1
  236.     # and the active object is always the editmode object.
  237.     ob_act = sce.objects.active
  238.     
  239.     if not ob_act or ob_act.type != 'Mesh':
  240.         BPyMessages.Error_NoMeshActive()
  241.         return 
  242.     
  243.     # Saves the editmode state and go's out of 
  244.     # editmode if its enabled, we cant make
  245.     # changes to the mesh data while in editmode.
  246.     is_editmode = Window.EditMode()
  247.     Window.EditMode(0)
  248.     
  249.     me = ob_act.getData(mesh=1) # old NMesh api is default
  250.     if len(me.faces)==0:
  251.         BPyMessages.Error_NoMeshFaces()
  252.         if is_editmode: Window.EditMode(1)
  253.         return
  254.     
  255.     # Create the variables.
  256.     PREF_THICK = Blender.Draw.Create(0.005)
  257.     PREF_SOLID = Blender.Draw.Create(1)
  258.     PREF_SHARP = Blender.Draw.Create(1)
  259.     PREF_XSHARP = Blender.Draw.Create(0)
  260.     
  261.     pup_block = [\
  262.     ('Thick:', PREF_THICK, 0.0001, 2.0, 'Skin thickness in mesh space.'),\
  263.     ('Solid Wire', PREF_SOLID, 'If Disabled, will use 6 sided wire segments'),\
  264.     ('Sharp Wire', PREF_SHARP, 'Use the original mesh topology for more accurate sharp wire.'),\
  265.     ('Extra Sharp', PREF_XSHARP, 'Use less geometry to create a sharper looking wire'),\
  266.     ]
  267.     
  268.     if not Blender.Draw.PupBlock('Solid Wireframe', pup_block):
  269.         if is_editmode: Window.EditMode(1)
  270.         return
  271.     
  272.     Window.WaitCursor(1)
  273.     t = sys.time()
  274.     
  275.     # Run the mesh editing function
  276.     solid_wire(ob_act, me, sce, PREF_THICK.val, PREF_SOLID.val, PREF_SHARP.val, PREF_XSHARP.val)
  277.     
  278.     # Timing the script is a good way to be aware on any speed hits when scripting
  279.     print 'Solid Wireframe finished in %.2f seconds' % (sys.time()-t)
  280.     Window.WaitCursor(0)
  281.     if is_editmode: Window.EditMode(1)
  282.     
  283.     
  284. # This lets you can import the script without running it
  285. if __name__ == '__main__':
  286.     main()
  287.